package com.soft.bams.server;

import com.soft.bams.entity.Account;
import com.soft.bams.exception.*;
import com.soft.bams.service.Bank;

import java.io.*;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yzh
 * @desc TODO
 * @date 2025/5/28
 */
public class ServerTask implements Runnable {
    private Socket clientSocket;
    private Bank bank;
    private String clientIP; // 记录客户端IP

    private static ConcurrentHashMap<Long, String> loggedAccounts = new ConcurrentHashMap<>();

    public ServerTask(Socket clientSocket) {
        this.clientSocket = clientSocket;
        this.bank = Bank.getInstance();
        this.clientIP = clientSocket.getRemoteSocketAddress().toString(); // 获取客户端IP
    }

    @Override
    public void run() {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
             ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream());
        ) {
            while (true) {
                String command = br.readLine();
                if (command == null) break;
                //System.out.println("收到命令: " + command);
                String[] parts = command.split("#");

                switch (parts[0]) {
                    case "login":
                        handleLogin(parts, oos);
                        break;
                    case "register":
                        handleRegister(parts, oos);
                        break;
                    case "deposit":
                        handleDeposit(parts, oos);
                        break;
                    case "withdraw":
                        handleWithdraw(parts, oos);
                        break;
                    case "transfer":
                        handleTransfer(parts, oos);
                        break;
                    case "updateCeiling":
                        handleUpdateCeiling(parts, oos);
                        break;
                    case "requestLoan":
                        handleRequestLoan(parts, oos);
                        break;
                    case "payLoan":
                        handlePayLoan(parts, oos);
                        break;
                    case "getBalance":
                        handleGetBalance(parts, oos);
                        break;
                    case "removeAccountFromMap":
                        handleRemoveAccountFromMap(parts, oos);
                        break;
                    default:
                        oos.writeObject("未知命令");
                }
            }
        } catch (Exception e) {
            System.err.println("客户端处理错误: " + e.getMessage());
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                System.err.println("关闭socket错误: " + e.getMessage());
            }
        }
    }

    // 处理登录
    private void handleLogin(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Long id = Long.parseLong(parts[1]);
            String password = parts[2];
            // 检查账户是否已登录
            if (loggedAccounts.containsKey(id)) {
                oos.writeObject("该账户已在其他客户端登录，请勿重复登录！");
                return;
            }
            Account account = bank.login(id, password);
            // 标记账户为已登录
            loggedAccounts.put(id, clientIP);
            //oos.reset();
            oos.writeObject(account);
        } catch (LoginException e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 处理注册
    private void handleRegister(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            String password = parts[1];
            String repassword = parts[2];
            String name = parts[3];
            String personID = parts[4];
            String email = parts[5];
            int type = Integer.parseInt(parts[6]);

            Account account = bank.register(password, repassword, name, personID, email, type);
            //oos.reset();
            oos.writeObject(account);
        } catch (RegisterException | TypeException e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 处理存款
    private void handleDeposit(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Long id = Long.parseLong(parts[1]);
            double money = Double.parseDouble(parts[2]);
            Account account = bank.deposit(id, money);
            oos.writeObject(account);
        } catch (LoginException | NotFoundException e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 处理取款
    private void handleWithdraw(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Long id = Long.parseLong(parts[1]);
            String password = parts[2];
            double money = Double.parseDouble(parts[3]);
            Account account = bank.withdraw(id, password, money);
            oos.writeObject(account);
        } catch (BalanceNotEnoughException | LoginException e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 处理转账
    private void handleTransfer(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Long from = Long.parseLong(parts[1]);
            String password = parts[2];
            Long to = Long.parseLong(parts[3]);
            double money = Double.parseDouble(parts[4]);

            bank.transfer(from, password, to, money);
            Account account = bank.getDao().selectOne(from);
            oos.writeObject(account);

        } catch (BalanceNotEnoughException | MoneyException | NotFoundException e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 处理更新透支额度
    private void handleUpdateCeiling(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Long id = Long.parseLong(parts[1]);
            String password = parts[2];
            double money = Double.parseDouble(parts[3]);

            bank.updateCeiling(id, password, money);
            Account account = bank.getDao().selectOne(id);
            oos.writeObject(account);
        } catch (TypeException | LoginException e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 处理贷款
    private void handleRequestLoan(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Long id = Long.parseLong(parts[1]);
            double money = Double.parseDouble(parts[2]);

            Account account = bank.requestLoan(id, money);
            oos.writeObject(account);
        } catch (LoanException | TypeException | LoginException e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 处理还贷
    private void handlePayLoan(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Long id = Long.parseLong(parts[1]);
            double money = Double.parseDouble(parts[2]);

            Account account = bank.payLoan(id, money);
            oos.writeObject(account);
        } catch (BalanceNotEnoughException | TypeException | LoginException e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 处理获取余额
    private void handleGetBalance(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Long id = Long.parseLong(parts[1]);
            Account account = bank.getDao().selectOne(id);
            oos.reset();
            oos.writeObject(account);
        } catch (Exception e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 处理map中移除账户id
    private void handleRemoveAccountFromMap(String[] parts, ObjectOutputStream oos) throws IOException {
        try {
            Long id = Long.parseLong(parts[1]);
            loggedAccounts.remove(id);
            oos.writeObject("已关闭当前界面");
        } catch (Exception e) {
            oos.writeObject(e.getMessage());
        }
    }

    // 获取登录IP信息
    public static ConcurrentHashMap<Long, String> getLoggedAccounts() {
        return loggedAccounts;
    }
}
